package com.zzy.ymcc.service.impl;


import com.zzy.utils.StrUtils;
import com.zzy.ymcc.domain.MessageSms;
import com.zzy.ymcc.dto.SmsCodeDto;
import com.zzy.ymcc.enums.GlobalExceptionCode;
import com.zzy.ymcc.exception.GlobalCustomException;
import com.zzy.ymcc.service.IMessageSmsService;
import com.zzy.ymcc.service.IVerifyCodeService;
import com.zzy.ymcc.utils.VerifyCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.concurrent.TimeUnit;


@Service
@Slf4j
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    private IMessageSmsService messageSmsService;
//    @Autowired
//    private UserMapper userMapper;

    @Override
    public String image(String key) {
        //使用工具类生成图形验证码
        String code = VerifyCodeUtils.generateVerifyCode(4);//1213
        //保存到redis
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);
        //使用工具类生成图形验证码编码之后的base64的字符串
        String base64Str = VerifyCodeUtils.verifyCode(110, 40, code);
        return base64Str;
    }


//    @Override
//    public void smsCode(SmsCodeDto smsCodeDto) {
//        // 空值校验
//        String imageCode = smsCodeDto.getImageCode();
//        String phone = smsCodeDto.getPhone();
//        String key = smsCodeDto.getImageCodeKey();
//        if(StringUtils.isEmpty(phone)){
//            throw new BusinessException("手机号码不能为空");
//        } if(StringUtils.isEmpty(imageCode)){
//            throw new BusinessException("图形验证码不能为空");
//        }
//        // 图形验证码是否过期 和 是否正确
//        Object o = redisTemplate.opsForValue().get(key);
//        if(o == null){
//            throw new BusinessException("图形验证码过期，请重新获取");
//        }
//        if(!o.toString().equalsIgnoreCase(imageCode)){
//            throw new BusinessException("图形验证码错误");
//        }

    @Override
    public void sendSms(SmsCodeDto smsCodeDto) {
        // 1.校验手机号格式是否正确
        if (smsCodeDto == null) {
            throw new GlobalCustomException(GlobalExceptionCode.PHONE_FORMAT_ERROR);
        }
        // 2.校验图形验证码

        String ImageCode = smsCodeDto.getImageCode();
        String phone = smsCodeDto.getPhone();
        String imageCodeKey = smsCodeDto.getImageKey();
        if(StringUtils.isEmpty(ImageCode)){
//            throw new BusinessException("图形验证码不能为空");
            throw new GlobalCustomException(GlobalExceptionCode.VERIFY_IS_EMPTY);
        }
        // 图形验证码是否过期 和 是否正确
        Object o = redisTemplate.opsForValue().get(imageCodeKey);
        if(o == null){
//            throw new BusinessException("图形验证码过期，请重新获取");
            throw new GlobalCustomException(GlobalExceptionCode.VERIFY_IS_OVERDUE);
        }
        if(!o.toString().equalsIgnoreCase(ImageCode)){
//            throw new BusinessException("图形验证码错误");
            throw new GlobalCustomException(GlobalExceptionCode.VERIFY_IS_ERROR);
        }
        // 3.拼接业务键，缺redis中查询Code
        String rediskey = "register" + phone;
        Object obj = redisTemplate.opsForValue().get(rediskey);
        System.out.println(obj);
        Date date = new Date();
        String code = "";
        if(obj != null){
            // 1.获取到value中的时间戳 2022年9月26日18:28:28
            String[] split = obj.toString().split(":");
            Long time = Long.valueOf(split[1]);
            // 2.判断时间是否超过了一分钟，如果当前时间，减去时间戳的时间大于一分钟就是合理的 ，如果小于一分钟就叫他稍后再试
            if(date.getTime()-time<60*1000){
                throw new GlobalCustomException(GlobalExceptionCode.OPERATING_FREQUENTLY_ERROR);
            }
            // 3.如果超过一分钟,是正常操作，继续沿用之前的code
            code = split[0];
        }else {
            // 4.如果不存在,那么我们重新生成一个验证码
            code = StrUtils.getRandomString(6);
        }
        // 5.将code+time 存入到redis中
        redisTemplate.opsForValue().set(rediskey,code+":"+date.getTime(),300*1000,TimeUnit.MILLISECONDS);
        // 6.储存消息，发送日志
        MessageSms messageSms = new MessageSms();
        messageSms.setTitle("注册验证码");
        // 7.提示用户验证码是多少，及时使用
        messageSms.setContent("您的验证码为" + code + ", 请在 5 分钟内使用");
        messageSms.setSendTime(date);
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String ip = request.getRemoteAddr();
        messageSms.setIp(ip);
        messageSmsService.insert(messageSms);
        // 8.发送短信验证码
        log.info("您的验证码为" + code + ", 请在 5 分钟内使用");

    }
//        // 校验手机验证码是否注册过
//        User user = userMapper.loadByPhone(phone);
//        if(user != null ){
//            throw new BusinessException("手机号码已经注册，请直接登录，忘记密码点忘记");
//        }
//        // 校验手机验证码是否过期
//        Object codeObj = redisTemplate.opsForValue().get("register:" + phone);
//        String smsCode = null;
//        // 1. 过期了或者没通过工具类生成
//        if(codeObj == null){
//            smsCode = StrUtils.getRandomString(4);
//        }else {
//            // 2. 没有过期还有用
//            // 2.1 判断是否过重发时间，利用时间戳相减 判断和60*1000 的大小关系
//            long oldTime = Long.parseLong(codeObj.toString().split(":")[1]);
//            // 2.2 如果没有过重发时间 是违规操作 抛异常
//            if((System.currentTimeMillis()-oldTime)<60*1000){// 没有过重发时间
//                throw new BusinessException("请勿频繁操作，请稍后再试");
//            }
//            // 2.3 如果过了重发时间【1分钟】 使用上面的验证码
//            smsCode = codeObj.toString().split(":")[0];
//        }
//        // 3. 保存到redis 重新设置3分钟过期
//        redisTemplate.opsForValue().set("register:"+phone,smsCode+":"+System.currentTimeMillis(),3, TimeUnit.MINUTES);
//        // 4. 调用工具类发送短信 sout作弊
//        //SmsUtils.sendSms(phone,"你的验证码为："+smsCode+",请在三分钟内使用");
//        System.out.println("你的验证码为："+smsCode+",请在三分钟内使用");
//    }
//
//    @Override
//    public void binderSmsCode(SmsCodeDto smsCodeDto) {
//        // 空值校验
//        String phone = smsCodeDto.getPhone();
//        if(StringUtils.isEmpty(phone)){
//            throw new BusinessException("手机号码不能为空");
//        }
//
//        // 校验手机验证码是否过期
//        Object codeObj = redisTemplate.opsForValue().get("binder:" + phone);
//        String smsCode = null;
//        // 1. 过期了或者没通过工具类生成
//        if(codeObj == null){
//            smsCode = StrUtils.getRandomString(4);
//        }else {
//            // 2. 没有过期还有用
//            // 2.1 判断是否过重发时间，利用时间戳相减 判断和60*1000 的大小关系
//            long oldTime = Long.parseLong(codeObj.toString().split(":")[1]);
//            // 2.2 如果没有过重发时间 是违规操作 抛异常
//            if((System.currentTimeMillis()-oldTime)<60*1000){// 没有过重发时间
//                throw new BusinessException("请勿频繁操作，请稍后再试");
//            }
//            // 2.3 如果过了重发时间【1分钟】 使用上面的验证码
//            smsCode = codeObj.toString().split(":")[0];
//        }
//        // 3. 保存到redis 重新设置3分钟过期
//        redisTemplate.opsForValue().set("binder:"+phone,smsCode+":"+System.currentTimeMillis(),3, TimeUnit.MINUTES);
//        // 4. 调用工具类发送短信 sout作弊
//        //SmsUtils.sendSms(phone,"你的验证码为："+smsCode+",请在三分钟内使用");
//        System.out.println("你的验证码为："+smsCode+",请在三分钟内使用");
//    }
}
